﻿#pragma once

#include <vector>
#include <string>

	
template<class K>
struct HashFunc
{
	size_t operator()(const K& key)
	{
		return (size_t)key;
	}
};

template<>
struct HashFunc<string>
{
	size_t operator()(const string& key)
	{
		size_t hash = 0;
		for (auto e : key)
		{
			hash *= 131;
			hash += e;
		}
		return hash;
	}
};


// 以下采用开放定址法，即线性探测解决冲突
namespace open_address
{
	enum State
	{
		EXIST,
		EMPTY,
		DELETE
	};

	template<class K, class V>
	struct HashData
	{
		pair<K, V> _kv;
		State _state = EMPTY;
	};

	template<class K, class V, class Hash = HashFunc<K>>
	class HashTable
	{
	public:
		inline unsigned long __stl_next_prime(unsigned long n)
		{
			// Note: assumes long is at least 32 bits.
			static const int __stl_num_primes = 28;
			static const unsigned long __stl_prime_list[__stl_num_primes] =
			{
				53, 97, 193, 389, 769,
				1543, 3079, 6151, 12289, 24593,
				49157, 98317, 196613, 393241, 786433,
				1572869, 3145739, 6291469, 12582917, 25165843,
				50331653, 100663319, 201326611, 402653189, 805306457,
				1610612741, 3221225473, 4294967291
			};
			const unsigned long* first = __stl_prime_list;
			const unsigned long* last = __stl_prime_list + __stl_num_primes;
			const unsigned long* pos = lower_bound(first, last, n);
			return pos == last ? *(last - 1) : *pos;
		}

		HashTable()
		{
			_tables.resize(__stl_next_prime(1));
		}

		bool Insert(const pair<K, V>& kv)
		{
			if (Find(kv.first))
				return false;

			// 扩容
			if ((double)_n / (double)_tables.size() >= 0.7)
			{
				// 获取素数表里面比当前表大的下一个素数
				size_t newsize = __stl_next_prime(_tables.size() + 1);

				HashTable<K, V, Hash> newHT;
				newHT._tables.resize(newsize);

				// 遍历旧表，将数据都映射到新表
				for (size_t i = 0; i < _tables.size(); ++i)
				{
					if (_tables[i]._state == EXIST)
					{
						newHT.Insert(_tables[i]._kv);
					}
				}
				_tables.swap(newHT._tables);
			}

			Hash hs;

			size_t hash0 = hs(kv.first) % _tables.size();
			size_t i = 1;
			size_t hashi = hash0;
			while (_tables[hashi]._state == EXIST)
			{
				// 线性探测
				hashi = (hash0 + i) % _tables.size();
				++i;
			}

			_tables[hashi]._kv = kv;
			_tables[hashi]._state = EXIST;
			++_n;

			return true;
		}

		HashData<K, V>* Find(const K& key)
		{
			Hash hs;
			size_t hash0 = hs(key) % _tables.size();
			size_t i = 1;
			size_t hashi = hash0;
			while (_tables[hashi]._state != EMPTY)
			{
				if (_tables[hashi]._state == EXIST &&
					_tables[hashi]._kv.first == key)
				{
					return &_tables[hashi];
				}
				hashi = (hash0 + i) % _tables.size();
				++i;
			}
			return nullptr;
		}

		bool Erase(const K& key)
		{
			// 伪删除 --> 就是不删除这个值，只是把这个值的标识状态改了，比如存在改为删除
			HashData<K, V>* del = Find(key);
			if (del == nullptr)
			{
				return false;
			}
			else
			{
				del->_state = DELETE;
				--_n;
				return true;
			}
		}


	private:
		vector<HashData<K, V>> _tables;
		size_t _n = 0;
	};


	void TestHT1()
	{
		HashTable<int, int> ht1;
		ht1.Insert({ 54, 1 });
		ht1.Insert({ 1, 1 });

		cout << ht1.Find(1) << endl;
		cout << ht1.Erase(54) << endl;
		cout << ht1.Find(1) << endl;
		cout << ht1.Find(54) << endl;

		/*for (int i = 0; i < 53; i++)
		{
			ht1.Insert({rand(), i});
		}*/
	}



	void TestHT2()
	{
		//HashTable<string, string, stringHashFunc> ht2;
		HashTable<string, string> ht2;
		ht2.Insert({ "sort", "排序" });
		ht2.Insert({ "string", "字符串" });
	}
}



/////////////////////////////////////////////////////////////////////////////////



namespace hash_bucket
{
	template<class K, class V>
	struct HashNode
	{
		pair<K, V> _kv;
		HashNode<K, V>* _next;
		HashNode(const pair<K, V>& kv)
			:_kv(kv)
			,_next(nullptr)
		{}
	};


	template<class K, class V>
	class HashTable
	{
		typedef HashNode<K, V> Node;
	public:
		inline unsigned long __stl_next_prime(unsigned long n)
		{
			// Note: assumes long is at least 32 bits.
			static const int __stl_num_primes = 28;
			static const unsigned long __stl_prime_list[__stl_num_primes] =
			{
				53, 97, 193, 389, 769,
				1543, 3079, 6151, 12289, 24593,
				49157, 98317, 196613, 393241, 786433,
				1572869, 3145739, 6291469, 12582917, 25165843,
				50331653, 100663319, 201326611, 402653189, 805306457,
				1610612741, 3221225473, 4294967291
			};
			const unsigned long* first = __stl_prime_list;
			const unsigned long* last = __stl_prime_list + __stl_num_primes;
			const unsigned long* pos = lower_bound(first, last, n);
			return pos == last ? *(last - 1) : *pos;
		}


		HashTable()
		{
			_tables.resize(__stl_next_prime(1), nullptr);
		}


		// 哈希桶的销毁
		~HashTable()
		{
			for (size_t i = 0; i < _tables.size(); ++i)
			{
				Node* cur = _tables[i];
				while (cur)
				{
					Node* next = cur->_next;
					delete cur;
					cur = next;
				}
				_tables[i] = nullptr;
			}
		}


		// 插入值为data的元素，如果data存在则不插入
		bool Insert(const pair<K, V>& kv)
		{
			if (Find(kv.first))
				return false;

			// 负载因子到1就扩容
			if (_n == _tables.size())
			{
				size_t newsize = __stl_next_prime(_tables.size() + 1);
				vector<Node*> newtables(newsize, nullptr);

				// 遍历旧表，把旧表的节点挪动到新表
				for (size_t i = 0; i < _tables.size(); ++i)
				{
					Node* cur = _tables[i];
					while (cur)
					{
						Node* next = cur->_next;

						// cur头插到新表
						size_t hashi = cur->_kv.first % newsize;
						cur->_next = newtables[hashi];
						newtables[hashi] = cur;

						cur = next;
					}
					_tables[i] = nullptr;
				}
				_tables.swap(newtables);
			}

			size_t hashi = kv.first % _tables.size();
			Node* newnode = new Node(kv);

			newnode->_next = _tables[hashi];
			_tables[hashi] = newnode;
			++_n;
			return true;
		}
		

		// 在哈希桶中查找值为key的元素，存在返回true否则返回false﻿
		Node* Find(const K& key)
		{
			size_t hashi = key % _tables.size();
			Node* cur = _tables[hashi];
			while (cur)
			{
				if (cur->_kv.first == key)
				{
					return cur;
				}
				cur = cur->_next;
			}
			return nullptr;
		}


		// 哈希桶中删除key的元素，删除成功返回true，否则返回false
		bool Erase(const K& key)
		{
			size_t hashi = key % _tables.size();
			Node* cur = _tables[hashi];
			Node* prev = nullptr;

			while (cur)
			{
				if (cur->_kv.first == key)
				{
					if (prev == nullptr)
					{
						// 头删
						_tables[hashi] = cur->_next;
					}
					else
					{
						prev->_next = cur->_next;
					}
					
					delete cur;
					return true;
				}
				prev = cur;
				cur = cur->_next;
			}
			return false;
		}


	private:
		vector<Node*> _tables;
		size_t _n = 0;
	};


	void TestHT1()
	{
		HashTable<int, int> ht1;
		ht1.Insert({ 54, 1 });
		ht1.Insert({ 1, 1 });

		for (int i = 0; i < 53; i++)
		{
			ht1.Insert({ rand(), i });
		}

		ht1.Erase(19895);
		ht1.Erase(15724);
	}
}